# -*- coding: utf-8 -*-
import ast
import json
import time
from collections import OrderedDict

import requests
from django.conf import settings

from async import async_job
from common.channel.base_pay import BasePay, SignMd5
from common.order.db import get_pay, add_pay_success
from common.utils import track_logging
from common.utils.exceptions import SignError

_LOGGER = track_logging.getLogger(__name__)

APP_CONF = {
    'YB19073118149': {
        'API_KEY': '42033f92d1d473517b5ceb1f025d797c',
    },
    'gateway': 'http://www.168kpay.com/api/v3/cashier.php',
    'query_gateway': 'http://www.168kpay.com/api/v3/query.php',
}

PAY_TYPE_DICT = {
    'alipay_h5': 'aph5',  # 支付宝h5
    'alipay': 'ap',  # 支付宝
    'wechat': 'wp',  # 微信
}


class NewZhongChengPay(BasePay, SignMd5):

    @staticmethod
    def pending_str(parameter, key, key_name='key', allow='no', not_sign=[]):
        s = 'merchant=%s&qrtype=%s&customno=%s&money=%s&sendtime=%s&notifyurl=%s&backurl=%s&risklevel=%s%s' % (
            parameter['merchant'], parameter['qrtype'], parameter['customno'], parameter['money'],
            parameter['sendtime'],
            parameter['notifyurl'], parameter['backurl'], parameter['risklevel'], key)
        return s

    # 异步回调签名验证
    def verify_notify_sign(self, parameter, key, app_id):

        pending_str = 'merchant=%s&merchant_money=%s&qrtype=%s&customno=%s&sendtime=%s&orderno=%s&' \
                      'money=%s&paytime=%s&state=%s%s' % (
                          parameter['merchant'], parameter['merchant_money'], parameter['qrtype'],
                          parameter['customno'],
                          parameter['sendtime'], parameter['orderno'], parameter['money'], parameter['paytime'],
                          parameter['state'], key)
        sign = parameter['sign']
        calculated_sign = self.md5_sign(pending_str)
        if sign != calculated_sign:
            _LOGGER.info("new_zhongchengpay sign: %s, calculated sign: %s", sign, calculated_sign)
            raise SignError('sign not pass, data: %s' % parameter)

    # 下单
    def create_charge(self, pay, pay_amount, info):
        app_id = info['app_id']
        service = info.get('service')
        api_key = self.get_api_key(APP_CONF, app_id)

        parameter_dict = OrderedDict((
            ('merchant', app_id),  # 商户号
            ('qrtype', self.get_pay_type(service, PAY_TYPE_DICT)),  # 支付类型
            ('customno', str(pay.id)),  # 订单号
            ('money', '%.2f' % (float(pay_amount))),  # 订单金额 元
            ('sendtime', str(int(round(time.time())))),  # 订单时间
            ('notifyurl', '{}/pay/api/{}/new/new_zhongchengpay/{}'.format(
                settings.NOTIFY_PREFIX, settings.NOTIFY_PATH, app_id)),
            ('backurl', ''),
            ('risklevel', '')  # 风险级别
        ))
        # 待签名字符串
        pending_str = self.pending_str(parameter_dict, api_key)
        parameter_dict['sign'] = self.md5_sign(pending_str)
        _LOGGER.info('new_zhongchengpay create_charge data:%s' % json.dumps(parameter_dict))
        url = self.get_url(parameter_dict, self.get_gateway(APP_CONF), pay)
        _LOGGER.info('new_zhongchengpay pay url: %s', url)
        return {'charge_info': url}

    # success异步回调
    def check_notify_sign(self, request, app_id):
        _LOGGER.info("new_zhongchengpay notify body: %s", request.body)
        data = dict(request.POST.iteritems())
        _LOGGER.info("new_zhongchengpay notify data: %s, order_id is: %s", data, data['customno'])
        self.verify_notify_sign(data, self.get_api_key(APP_CONF, app_id), app_id)
        pay_id = data['customno']
        pay = self.check_ip_pay_status(request, pay_id, channel_name='new_zhongchengpay', data=data)
        if not pay:
            return 'OK'  # 返回给渠道的信息

        mch_id = pay.mch_id
        trade_status = str(data['state'])
        trade_no = data['orderno']  # 平台订单号
        total_fee = float(data['money'])
        extend = {
            'trade_status': trade_status,
            'trade_no': trade_no,
            'total_fee': total_fee,
        }
        if trade_status == '1':
            self.check_channel_order(pay_id, total_fee, app_id)
            _LOGGER.info('new_zhongchengpay check order success, user_id:%s pay_id:%s' % (mch_id, pay_id))
            add_pay_success(mch_id, pay_id, total_fee, trade_no, extend)
            # async notify
            async_job.notify_mch(pay_id)
            return 'OK'

    # 订单查询
    def query_charge(self, pay_order, app_id):
        pay_id = pay_order.id
        api_key = self.get_api_key(APP_CONF, app_id)
        pay = get_pay(pay_id)
        parameter_dict = OrderedDict((
            ('merchant', app_id),  # 商户ID
            ('customno', str(pay_id)),  # 平台订单号
            ('sendtime', str(int(round(time.time())))),  # 订单时间
        ))
        # 待签名字符串
        pending_str = 'merchant=%s&customno=%s&sendtime=%s%s' % (
            parameter_dict['merchant'], parameter_dict['customno'], parameter_dict['sendtime'], api_key)
        parameter_dict['sign'] = self.md5_sign(pending_str)

        json_parameter = json.dumps(parameter_dict)
        _LOGGER.info('new_zhongchengpay query data %s, order_id is: %s', json_parameter,
                     pay.id)
        response = requests.post(self.get_query_geteway(APP_CONF), data=parameter_dict, timeout=5)
        data = json.loads(response.text)
        _LOGGER.info('new_zhongchengpay query rsp, %s', data)
        if data['errCode'] == '0':
            data = data['data']
            trade_status = str(data['state'])
            total_fee = float(data.get('money'))
            trade_no = str(data['customno'])
            extend = {
                'trade_status': trade_status,
                'trade_no': trade_no,
                'total_fee': total_fee,
            }
            # 1:支付成功; 0:未支付/支付失败  -1:订单关闭
            if trade_status == '1':
                self.check_channel_order(pay_id, total_fee, app_id)
                _LOGGER.info('new_zhongchengpay query order success, mch_id:%s pay_id:%s' % (pay_order.mch_id, pay_id))
                add_pay_success(pay_order.mch_id, pay_id, total_fee, trade_no, extend)
                async_job.notify_mch(pay_order.id)
            else:
                _LOGGER.info('new_zhongchengpay query order success,but not pay success,status:%s ' % trade_status)
        else:
            _LOGGER.warn('new_zhongchengpay data error, msg: %s', data['data'])


def create_charge(pay, pay_amount, info):
    return NewZhongChengPay().create_charge(pay, pay_amount, info)


def check_notify_sign(request, app_id):
    return NewZhongChengPay().check_notify_sign(request, app_id)


def query_charge(pay_order, app_id):
    NewZhongChengPay().query_charge(pay_order, app_id)
